package org.heydr;

import java.util.Queue;
import java.util.concurrent.TimeUnit;

import org.apache.http.HttpStatus;
import org.heydr.common.TaskEngine;
import org.heydr.common.http.HttpSnatcher;
import org.heydr.common.http.StringUtils;
import org.heydr.entity.HttpSnatchParam;
import org.heydr.entity.Page;
import org.heydr.entity.Site;
import org.heydr.entity.Url;
import org.heydr.handler.HeyDrHandler;

public abstract class Crawler implements Runnable{
	
	/* the waiting urls queue */
	private Queue<Url> queue;
	/* snatch frequency,default:2000ms */
	private static long SLEEP_FREQUENCY = 2000;
	
	public Queue<Url> getQueue() {
		return queue;
	}
	public void setQueue(Queue<Url> queue) {
		this.queue = queue;
	}
	public void addToQueue(Url url){
		this.queue.add(url);
	}
	public static void setFREQUENCY(long fREQUENCY) {
		SLEEP_FREQUENCY = fREQUENCY;
	}

	@Override
	public void run() {
		
		while(true){
			handle();
			try {
				//when waiting url queue is empty,suspend transation and sleep
				TimeUnit.MILLISECONDS.sleep(SLEEP_FREQUENCY);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	/**
	 * description:begin crawling transation
	 * @param queue
	 * @return:void
	 * @author carlos.xie
	 * 2013-5-20
	 */
	private void handle(){
		while(!queue.isEmpty()){
			System.out.println("still "+queue.size()+" in it.");
			Url url = queue.poll();//poll out an availble url to crawl
			if(null != url){
				String md5Url = StringUtils.md5(url.getUrl());
				if(TaskEngine.alreadySnatched(md5Url)){
					//TODO: skip the url which has been snatched.
				}else{
					snatch(url);
				}
			}
		}
		//now the queue is empty,alarm the task engine to refresh the queue.
		TaskEngine.emptyAlarm();
	}
	
	/**
	 * description:connect to internet and snatch html content
	 * @param url
	 * @return:void
	 * @author carlos.xie
	 * 2013-5-20
	 */
	public void snatch(Url url){
		Site site = TaskEngine.getSite(url.getSite());
		HttpSnatchParam httpSnatchParam = null;
		if(null != site){
			//request params and proxy setting
			httpSnatchParam = site.getHttpSnatchParam();
		}
		if(null == httpSnatchParam)
			httpSnatchParam = new HttpSnatchParam();
		httpSnatchParam.setUrl(url.getUrl());
		
		Page page = HttpSnatcher.getPage(httpSnatchParam);
		
		String handlerTag = url.getHandleTag();
		HeyDrHandler handler = getHandler(handlerTag);
		handler.handle(url, page);
		try {
			if(null != site){
				TimeUnit.MILLISECONDS.sleep(site.getSleepTime());
			}else{
				TimeUnit.MILLISECONDS.sleep(SLEEP_FREQUENCY);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	private HeyDrHandler getHandler(String handlerTag){
		HeyDrHandler handler = TaskEngine.matchHandlerChain(handlerTag);
		if(null == handler)
			throw new NullPointerException(handlerTag + " handler couldn't be matched.");
		return handler;
	}
	
}